package me.mingshan.leetcode;

/**
 * https://leetcode.cn/problems/house-robber-ii/description/
 * <p>
 * 213. 打家劫舍 II
 * <p>
 * 你是一个专业的小偷，计划偷窃沿街的房屋，每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈
 * ，这意味着第一个房屋和最后一个房屋是紧挨着的。同时，相邻的房屋装有相互连通的防盗系统，如果两间相邻的房屋在同一晚上被小偷闯入，系统会自动报警 。
 * <p>
 * 给定一个代表每个房屋存放金额的非负整数数组，计算你 在不触动警报装置的情况下 ，今晚能够偷窃到的最高金额。
 * <p>
 * <p>
 * <p>
 * 示例 1：
 * <p>
 * 输入：nums = [2,3,2]
 * 输出：3
 * 解释：你不能先偷窃 1 号房屋（金额 = 2），然后偷窃 3 号房屋（金额 = 2）, 因为他们是相邻的。
 * 示例 2：
 * <p>
 * 输入：nums = [1,2,3,1]
 * 输出：4
 * 解释：你可以先偷窃 1 号房屋（金额 = 1），然后偷窃 3 号房屋（金额 = 3）。
 * 偷窃到的最高金额 = 1 + 3 = 4 。
 * 示例 3：
 * <p>
 * 输入：nums = [1,2,3]
 * 输出：3
 *
 * @author hanjuntao
 * @date 2025/7/28 0028
 */
public class L_213_house_robber_ii {

    public static void main(String[] args) {
        int[] nums = new int[]{1, 2, 3, 1};
        System.out.println(rob(nums)); // 4
    }

    /**
     * 思路：
     * <p>
     * 原先打家劫舍 起点为0，终点为n-1
     * <p>
     * 现在是一个环形，起点与终点不能同时偷：
     * <p>
     * 1. 偷第一个，不偷最后一个
     * 2. 不偷第一个，偷最后一个
     * <p>
     * 比较两个的值，取较大的
     * <p>
     * 状态转移方程：
     * <p>
     * dp[i] = Math.max(dp[i-2] + nums[i-1], dp[i-1])
     *
     * @param nums
     * @return
     */
    public static int rob(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        }

        if (nums.length == 1) {
            return nums[0];
        }

        int n = nums.length;

        int max = 0;

        // 不偷第一间，则从第二间开始偷
        int[] dp = new int[n + 1];
        dp[0] = 0;
        dp[1] = 0;
        dp[2] = nums[1];

        for (int i = 3; i <= n; i++) {
            dp[i] = Math.max(dp[i - 2] + nums[i - 1], dp[i - 1]);
        }

        max = Math.max(dp[n], max);

        // 不偷最后一间，则从第一间开始偷
        dp = new int[n + 1];
        dp[0] = 0;
        dp[1] = nums[0];

        for (int i = 2; i <= n - 1; i++) {
            dp[i] = Math.max(dp[i - 2] + nums[i - 1], dp[i - 1]);
        }

        max = Math.max(dp[n - 1], max);

        return max;
    }

}
